#include "8255.h"

// Array of LED number: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, dp
u8 segdata[11] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x7f};

// Hello info: HELLO 66
u8 helloinfo[8] = {0x89, 0x86, 0xc7, 0xc7, 0xc0, 0xff, 0x82, 0x82};
                   
void init8255(){
    outportb(CRL_ADDR_8255, 0x88);  // Port A, B output, port C high 4 bits input, low 4 bits output
}

void initLED(){
    u8 i = 450000;
    while(i--){
        outportb(PA_ADDR_8255, helloinfo[0]);
        outportb(PB_ADDR_8255, 0x7f);
        delay(1);
        outportb(PA_ADDR_8255, helloinfo[1]);
        outportb(PB_ADDR_8255, 0xbf);
        delay(1);
        outportb(PA_ADDR_8255, helloinfo[2]);
        outportb(PB_ADDR_8255, 0xdf);
        delay(1);
        outportb(PA_ADDR_8255, helloinfo[3]);
        outportb(PB_ADDR_8255, 0xef);
        delay(1);
        outportb(PA_ADDR_8255, helloinfo[4]);
        outportb(PB_ADDR_8255, 0xf7);
        delay(1);
        outportb(PA_ADDR_8255, helloinfo[5]);
        outportb(PB_ADDR_8255, 0xfb);
        delay(1);
        outportb(PA_ADDR_8255, helloinfo[6]);
        outportb(PB_ADDR_8255, 0xfd);
        delay(1);
        outportb(PA_ADDR_8255, helloinfo[7]);
        outportb(PB_ADDR_8255, 0xfe);
        delay(1);
    }
}

void delay(u16 ms){
    u16 i;
	while(ms--){
		i = 150;
		while (--i){;}
	}
}

void scanLED(u8 minute, u8 hour){
    outportb(PA_ADDR_8255, segdata[minute % 10]);
    outportb(PB_ADDR_8255, 0xfe);                   // LED0
    delay(1);
    outportb(PA_ADDR_8255, segdata[minute / 10]);
    outportb(PB_ADDR_8255, 0xfd);                   // LED1
    delay(1);
    outportb(PA_ADDR_8255, segdata[hour % 10]);
    outportb(PB_ADDR_8255, 0xfb);                   // LED2
    delay(1);
    outportb(PA_ADDR_8255, segdata[hour / 10]);
    outportb(PB_ADDR_8255, 0xf7);                   // LED3
    delay(1);
}

void scanDP(u8 flag){
    if (flag){
        outportb(PA_ADDR_8255, segdata[10]);
        outportb(PB_ADDR_8255, 0xef);
        delay(1);
        // Turn on LED3_DP
    }
    else{
        outportb(PA_ADDR_8255, 0xff);
        outportb(PB_ADDR_8255, 0xef);
        delay(1);
        // Turn off LED3_DP
    }
}

u8 scanKeyboard(){
    u8 temp;
    u8 result;
    while(1){
        result = inportb(PC_ADDR_8255);         // Simply check if any key is being pressed
        result |= 0x0f;                         
        if(result == 0xff)
            break;
        result = scanKeyboard2();               // Transfer digital signal to digital value
        if(result == 0xff)                      // Over one key are being pressed
            continue;
        delay(20);
        delay(20);
        if(result == scanKeyboard2()){
            do{
                temp = inportb(PC_ADDR_8255);
                temp |= 0x0f;
            } while(temp != 0xff);              // Continue only when release the key
            break;
        }
    }
    return result;
}

u8 scanKeyboard2(){
    u8 result;
    u8 temp = inportb(PC_ADDR_8255);
    temp |= 0x0f;
    switch (temp)
    {
    case 0xef:
        result = 4;
        break;
    default:
        result = 0xff;
        break;
    }
    return result;
}